/*
 * Copyright (C) 2012 Matthias Zeimer and the miniframes community.
 * All rights reserved. 
 * 
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.opensource.org/licenses/EPL-1.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.miniframes.minijpa;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collection;

import javax.persistence.NamedQuery;
import javax.persistence.Query;

/**
 * <p>
 * An enquiry to a database.
 * </p>
 * 
 * <p>
 * This annotation marks a method which is an enquiry to a database. Each method
 * argument is used for the matching parameter of the underlying query. The
 * arguments for this parameters are selected with the respective value of
 * {@link Parameter#parameterName()}. These methods are placed in an interface
 * declaration. As recommendation the interface is a sub-type of
 * {@link DatabaseInterface}.
 * </p>
 * 
 * <p>
 * Examples (inspired by the Java&#8482; persistence documentation):
 * </p>
 * 
 * <p>
 * Using a {@link NamedQuery}:
 * 
 * <pre>
 * &#064;DatabaseEnquiryMethod(
 *         namedQuery = &quot;find_all_customers_with_name&quot;)
 * Collection&lt;Customer&gt; findAllCustomersWithName(
 *         &#064;Parameter(parameterName=&quot;custName&quot;) String name);
 * </pre>
 * 
 * Using a Java&#8482; Persistence query string:
 * 
 * <pre>
 * &#064;DatabaseEnquiryMethod(
 *         query = &quot;SELECT c FROM Customer c WHERE c.name LIKE :custName&quot;)
 * Collection&lt;Customer&gt; findAllCustomersWithName(
 *         &#064;Parameter(parameterName=&quot;custName&quot;) String name);
 * </pre>
 * 
 * Exactly one of the two query types shown above need to be used for one
 * method. The query types could differ between different methods in an
 * interface. The result type of the query is determined from the result of the
 * annotated method and checked against it. Allowed collection types are
 * {@link Iterable} and {@link Collection}; other collection types will follow
 * in future versions with restrictions for their use (for example
 * (IdentityEquals)Set for distinct selects and List for queries with order-by
 * clause).
 * </p>
 * 
 * @author Matthias Zeimer
 * @version 3
 * @since 0.1.1, 2012-06-18
 */
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DatabaseEnquiryMethod {

    /**
     * <p>
     * The name of the underlying {@linkplain NamedQuery named query}.
     * </p>
     * 
     * <p>
     * May only be specified if {@link #query()} is not specified.
     * </p>
     * 
     * @return the query name as described above.
     * @see NamedQuery
     */
    String namedQuery() default "";

    /**
     * <p>
     * The underlying {@linkplain Query query} as Java&#8482; Persistence query
     * string.
     * </p>
     * 
     * <p>
     * May only be specified if {@link #namedQuery()} is not specified.
     * </p>
     * 
     * @return the query as described above.
     * @see NamedQuery
     */
    String query() default "";

    /**
     * <p>
     * The {@link TransactionMode} to be used for the annotated enquiry method.
     * The default is {@link TransactionMode#REQUIRES_OPEN_TRANSACTION
     * REQUIRES_OPEN_TRANSACTION}.
     * </p>
     * 
     * @return The mode to use.
     * @see TransactionMode
     */
    TransactionMode transactionMode() default TransactionMode.REQUIRES_OPEN_TRANSACTION;
}
